package com.jphoebe.plugin.mybatis.generate;

import com.google.common.base.Optional;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiClassImplUtil;
import com.intellij.psi.impl.source.PsiClassReferenceType;
import com.intellij.psi.impl.source.PsiImmediateClassType;
import com.jphoebe.plugin.mybatis.dom.attribute.GroupTwo;
import com.jphoebe.plugin.mybatis.dom.attribute.Mapper;
import com.jphoebe.plugin.mybatis.dom.attribute.Select;
import com.jphoebe.plugin.mybatis.utils.jetbrain.JetbrainJavaUtil;
import org.jetbrains.annotations.Nullable;

import java.util.Arrays;
import java.util.List;

/**
 * SimpleSqlGenerate class
 *
 * @author 蒋时华
 * @date 2019/2/25
 */
public class SimpleSqlGenerate {

    private static final String INSERT = "insert";
    private static final String DELETE = "delete";
    private static final String UPDATE = "update";
    private static final String SELECT = "select";

    public static GroupTwo addGenerate(Mapper mapper, String sqlType, PsiMethod method, Editor editor){
        if(INSERT.equals(sqlType)){
            return mapper.addInsert();
        }else if(DELETE.equals(sqlType)){
            return mapper.addDelete();
        }else if(UPDATE.equals(sqlType)){
            return mapper.addUpdate();
        }else if(SELECT.equals(sqlType)){
            Optional<PsiClass> selectResultType = getSelectResultType(method);
            // resultType check
            if(!selectResultType.isPresent()){
                // 输出对象不存在
                HintManager.getInstance().showErrorHint(editor, "Target bean is not Present");
                return null;
            }
            Optional<PsiClass> selectParameterType = getSelectParameterType(method);
            // parameterType check
            // 非基本参数类型
            if(selectParameterType!=null){
                if(!selectParameterType.isPresent()){
                    HintManager.getInstance().showErrorHint(editor, "Parameter bean is not Present");
                    return null;
                }
            }
            Select select = mapper.addSelect();
            // 添加 resultType
            select.getResultType().setValue(selectResultType.get());
            // 添加 parameterType
            if(selectParameterType!=null){
                select.getParameterType().setValue(selectParameterType.get());
            }
            return select;
        }else{
            return null;
        }
    }

    private static Optional<PsiClass> getSelectResultType(@Nullable PsiMethod method) {
        if (null == method) {
            return Optional.absent();
        }
        PsiType returnType = method.getReturnType();
        if (returnType instanceof PsiPrimitiveType && returnType != PsiType.VOID) {
            return JetbrainJavaUtil.findClazz(method.getProject(), ((PsiPrimitiveType) returnType).getBoxedTypeName());
        } else if (returnType instanceof PsiClassReferenceType) {
            PsiClassReferenceType type = (PsiClassReferenceType) returnType;
            if (type.hasParameters()) {
                PsiType[] parameters = type.getParameters();
                if (parameters.length == 1) {
                    type = (PsiClassReferenceType) parameters[0];
                }
            }
            return Optional.fromNullable(type.resolve());
        }
        return Optional.absent();
    }

    private static Optional<PsiClass> getSelectParameterType(@Nullable PsiMethod method) {
        if (null == method) {
            return Optional.absent();
        }
        List<String> baseClass = Arrays.asList("String", "Float", "Byte", "Double", "Short", "Integer", "Long", "Boolean", "Character");
        PsiParameterList parameterList = method.getParameterList();
        int beanNumber = 0;
        Optional<PsiClass> finalBean = null;
        for (PsiParameter psiParameter : parameterList.getParameters()) {
            PsiType parameterType = psiParameter.getType();
            if (parameterType instanceof PsiClassReferenceType && !baseClass.contains(((PsiClassReferenceType) parameterType).getClassName())) {
                PsiClassReferenceType type = (PsiClassReferenceType) parameterType;
                if (type.hasParameters()) {
                    PsiType[] parameters = type.getParameters();
                    if (parameters.length == 1) {
                        type = (PsiClassReferenceType) parameters[0];
                    }
                }
                finalBean = Optional.fromNullable(type.resolve());
                beanNumber++;
            }
        }
        if(beanNumber==0){
            return null;
        }else if(beanNumber==1){
            return finalBean;
        }else{
            return Optional.absent();
        }
    }

}
